package com.spring.nio.mysql.handshake;

import lombok.Data;

/**
 * @author : pangfuzhong
 * @description
 * @date : 2021/8/7 17:04
 */
@Data
public class HandshakePacket {
    private static final byte[] EMPTY_BYTES = new byte[0];
    private static final byte[] FILLER_13 = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    private final byte[] data;
    private final int totalLength;
    private int position;

    public HandshakePacket(byte[] data) {
        this.data = data;
        this.totalLength = data.length;
        this.position = 0;
    }

    /**
     * mysql 协议版本号 1byte
     * */
    private byte protocolVersion;

    /**
     * mysql服务端版本字节数据 字节长度不固定
     * */
    private byte[] serverVersion;
    /**
     * 4byte 线程ID, 当前连接所属mysql线程id
     * */
    private Integer threadId;
    /**
     * 8byte 挑战随机数第一部分
     * */
    private byte[] seed1;
    /**
     * 8byte 挑战随机数第二部分
     * */
    private byte[] seed2;
    /**
     * 1byte 填充标志位
     * */
    private byte fillByte;

    /**
     * 2byte 服务器权能标志1
     * */
    private int serverCapabilities;

    /**
     * 1byte 字符编码
     * */
    private byte serverCharsetIndex;

    /**
     * 2byte 服务状态
     * */
    private int serverStatus;

    /**
     * 2byte 服务器权能标志2
     * */
   // private int serverCapabilitiesSecond;

    /**
     * 1byte 挑战长度未使用
     * */
    private int challengeLength;

    /**
     *
     * */
    private byte[] restOfScrambleBuff;

    public byte readOneByte() {
        return this.data[position++];
    }

    public int read2BytesToInt() {
        final byte[] b = this.data;
        int i = b[position++] & 0xff;
        i |= (b[position++] & 0xff) << 8;
        return i;
    }

    public int read3BytesToInt() {
        final byte[] b = this.data;
        int i = b[position++] & 0xff;
        i |= (b[position++] & 0xff) << 8;
        i |= (b[position++] & 0xff) << 16;
        return i;
    }

    public int read4BytesInt() {
        final byte[] b = this.data;
        int i = b[position++] & 0xff;
        i |= (b[position++] & 0xff) << 8;
        i |= (b[position++] & 0xff) << 16;
        i |= (b[position++] & 0xff) << 24;
        return i;
    }

    public long readUB4() {
        final byte[] b = this.data;
        long l = (long) (b[position++] & 0xff);
        l |= (long) (b[position++] & 0xff) << 8;
        l |= (long) (b[position++] & 0xff) << 16;
        l |= (long) (b[position++] & 0xff) << 24;
        return l;
    }

    /**
     * 读取直到字节值为0则终止
     * */
    public byte[] readLoopUtilZeroByte() {
        final byte[] b = this.data;
        if (this.position >= this.totalLength) {
            return EMPTY_BYTES;
        }
        int offset = -1;
        for (int i = this.position; i < this.totalLength; i++) {
            if (b[i] == 0) {
                offset = i;
                break;
            }
        }
        switch (offset) {
            case -1:
                byte[] ab1 = new byte[this.totalLength - this.position];
                System.arraycopy(b, position, ab1, 0, ab1.length);
                this.position = this.totalLength;
                return ab1;
            case 0:
                this.position++;
                return EMPTY_BYTES;
            default:
                byte[] ab2 = new byte[offset - this.position];
                System.arraycopy(b, this.position, ab2, 0, ab2.length);
                // 注释掉，放置position跳过不该跳过的
                this.position = offset + 1;
                return ab2;
        }
    }

    public byte[] move(int i) {
        int current = position;
        position += i;
        byte[] returnBytes = new byte[i];
        int k = 0;
        for(int index = current; index < position; index++) {
            returnBytes[k] = this.data[index];
            k++;
        }

        return returnBytes;
    }
}
